
/*
*******************************************************************************
**
**    Project           : OLED160X128-Dev-Rev1A
**    Compiler          : MPLAB
**    Date              : 2010-3-7 
**    Author            : ElabGuy
**    Abstract          : Contains the OLED low level drivers and high level functions
**                      : for text display demo on the OLED160X128-DEV-V1C module
**
**    Copyright (c) 2009-2010 www.ElabGuy.com
**    All rights reserved.
**
*******************************************************************************
*/

#include 	<stdlib.h>
#include 	<plib.h>
#include 	"HardwareProfile.h"
#include 	"oled160X128.h"
#include 	"OLED_Font.h"


/*
**=============================================================================
**   Global variables
**=============================================================================
*/

  U8 OLED_CursorX;
  U8 OLED_CursorY;
  U8 OLED_Red;
  U8 OLED_Green;
  U8 OLED_Blue;

/*
**=============================================================================
**  Internal function prototypes
**=============================================================================
*/
void OLED_Reset(void);
void Write_Register(U8 data);
void Write_Parameter(U8 data);
void Write_Command(U8 Reg, U8 data);
void Write_6BitDDRAM(U8 data);
void fill_block(U8 R,U8 G,U8 B);
void ColorR(void);
void ColorG(void);
void ColorB(void);
void ColorW(void);
void Clear_DDRAM(void);
void OLED_Delay(U16 time);
void OLED_Init(void);
void OLED_Set_Cursor(U8 X, U8 Y);
void OLED_Set_Image_Position(U8 X, U8 Y);
void text_test(void);
void fill_text_panel(U8 r, U8 g, U8 b);


/*
**=============================================================================
** Internal variables
**=============================================================================
*/

static      char	buffer[128];


/*************OLED Low level functions**************/

void OLED_Set_Cursor(U8 X, U8 Y)
{
	Write_Command(rMEMORY_ACCESS_POINTER_X,X);//Reg:20h Action:Memory X start addr.
	Write_Command(rMEMORY_ACCESS_POINTER_Y,Y);//Reg:21h Action:Memory Y start addr.
}

void OLED_Set_Image_Position(U8 X, U8 Y)
{
	Write_Command(rMEMORY_ACCESS_POINTER_X,X);//Reg:20h Action:Memory X start addr.
	Write_Command(rMEMORY_ACCESS_POINTER_Y,Y);//Reg:21h Action:Memory Y start addr.
	OLED_CursorX = X; //Save current cursor X
	OLED_CursorY = Y; //Save current cursor Y
}

void OLED_Set_Color(U8 R, U8 G, U8 B)
{
	OLED_Red 	= R;
	OLED_Green	= G;
	OLED_Blue 	= B;
}

void OLED_Reset(void)
{
	RESET_ENABLE;
	OLED_Delay(0x10);
	RESET_DISABLE;
	OLED_Delay(0x10);
}

void Write_Register(U8 data)
{
	PORTE &= 0x300; //resett D0-D7
	OLED_COMMAND;
	CS_ENABLE;
	WD_ENABLE
	PORTE |= data;
	WD_DISABLE 
	CS_DISABLE 
	OLED_DATA
}

void Write_Parameter(U8 data)
{
	PORTE &= 0x300; //resett D0-D7
	OLED_DATA;
	CS_ENABLE;
	WD_ENABLE
	PORTE |= data;
	WD_DISABLE 	
	CS_DISABLE 
}

void Write_Command(U8 Reg, U8 data)
{
	Write_Register(Reg);
	Write_Parameter(data);
}

void Write_6BitDDRAM(U8 data)
{
	PORTE &= 0x300; //resett D0-D7
	OLED_DATA;
	CS_ENABLE;
	WD_ENABLE 
	PORTE = PORTE | (data<<2);
	WD_DISABLE 	
	CS_DISABLE 
}

/*************OLED High level functions**************/
void fill_block(U8 R,U8 G,U8 B)		//fill the whole panel with the same color				
{
	U8 i,j;
	Write_Register(rDDRAM_DATA_ACCESS_PORT);
	for(i=0;i<128;i++)
	{
		for(j=0;j<160;j++)
		{
			Write_6BitDDRAM(R);
			Write_6BitDDRAM(G);
			Write_6BitDDRAM(B);
		}
	}
}


void ColorR(void)					//fill the whole panel with Red color
{
	fill_block(0x3f,0x00,0x00);
}
void ColorG(void)					//fill the whole panel with Green color
{
	fill_block(0x00,0x3f,0x00);
}
void ColorB(void)					//fill the whole panel with Blue color
{
	fill_block(0x00,0x00,0x3f);
}
void ColorW(void)					//fill the whole panel with White color
{	
	fill_block(0x3f,0x3f,0x3f);
}
void Clear_DDRAM(void)				// Clear the Panel
{
	fill_block(0x00,0x00,0x00);
}

void OLED_Delay(U16 time)			//Delay function
{
	U16 i,j;
	
	for(j=time;j>0;j--)
	{
		for(i=0;i<1024;i++)  
		{}
	}
}

void text_test(void)			// Text and Color Test function
{
	U8 r,g,b;

	OLED_Set_Image_Position(10, 0);

	OLED_Set_Color(0x3F,0x00,0x00);
 	OLED_Puts( "O" );

	OLED_Set_Color(0x00,0x3F,0x00);
 	OLED_Puts( "L" );

	OLED_Set_Color(0x00,0x00,0x3F);
 	OLED_Puts( "E" );

	OLED_Set_Color(0x3F,0x3F,0x3F);
 	OLED_Puts( "D" );

	OLED_Set_Color(0x3F,0x3F,0x00);
 	OLED_Puts( "160" );

	OLED_Set_Color(0x00,0x3F,0x3F);
 	OLED_Puts( "X" );

	OLED_Set_Color(0x3F,0x00,0x3F);
 	OLED_Puts( "128" );

	OLED_Set_Color(0x00,0x3F,0x3F);
 	OLED_Puts( "-" );

	OLED_Set_Color(0x3F,0x3F,0x3F);
 	OLED_Puts( "DEV" );

	r=0x00;
	g=0X00;
	b=0x00;	

	for(r=0x1;r<0x3F;r+=1)
	{
		fill_text_panel(r,g,b);
	}

	for(g=0x1;g<0x3F;g+=1)
	{
		fill_text_panel(r,g,b);
	}

	for(r=0x3F;r>0;r-=1)
	{
		fill_text_panel(r,g,b);
	}

	for(b=0x1;b<0x3F;b+=1)
	{
		fill_text_panel(r,g,b);
	}

	for(g=0x3F;g>0;g-=1)
	{
		fill_text_panel(r,g,b);
	}

	for(r=0x1;r<0x3F;r+=1)
	{
		fill_text_panel(r,g,b);
	}

	for(g=0x1;g<0x3F;g+=1)
	{
		fill_text_panel(r,g,b);
	}
	
	for(r=0x3F;r>0;r-=1)
	{
		fill_text_panel(r,g,b);
		g--;
		b--;
	}

	for(r=0x1;r<=0x3F;r+=1)
	{
		g++;
		b++;
		fill_text_panel(r,g,b);
	}
}

void fill_text_panel(U8 r, U8 g, U8 b) 	// Hello World Text test function
{
		OLED_Set_Color(0x3F,0x00,0x00);
		OLED_Set_Image_Position(30, 20);
		sprintf(buffer, "   Red: %lu   ", r);
 		OLED_Puts(buffer);

		OLED_Set_Color(0x00,0x3F,0x00);
		OLED_Set_Image_Position(30, 38);
		sprintf(buffer, "Green: %lu    ", g);
 		OLED_Puts(buffer);

		OLED_Set_Color(0x00,0x00,0x3F);
		OLED_Set_Image_Position(30, 56);
		sprintf(buffer, "  Blue: %lu   ", b);
 		OLED_Puts(buffer);

		OLED_Set_Color(r,g,b);
		OLED_Set_Image_Position(25, 80);
		OLED_Puts( "Hellow World!!" );
		
		OLED_Set_Image_Position(12, 105);
		OLED_Set_Color(r,g,b);
		OLED_Puts( "www.ElabGuy.com" );

		OLED_Delay(0x80);
}

void fill_color_panel(void)					// Fill the whole Panel with Rainbow
{
	U16 x,y;
	U16 r,g,b;
	r=63;
	g=b=0;

	for(y=0;y<128;y++)
	{
		r=63;
		g=b=0;

		
		for(x=0;x<160;x++)
		{
			OLED_Set_Cursor(x,y);
			OLED_Set_Color(r,g,b);
			Write_Register(rDDRAM_DATA_ACCESS_PORT);
			Write_6BitDDRAM(OLED_Red);
			Write_6BitDDRAM(OLED_Green);
			Write_6BitDDRAM(OLED_Blue);

			if(x<30)
			{
				g+=2;
				if(g>=63)
					g=63;
			}
			if(x>=30 && x<60)
			{
				r-=2;
				if(r<=0)
					r=0;
			}
			if(x>=60 && x<90)
			{
				b+=2;
				if(b>=63)
					b=63;
			}
			if(x>=90 && x<120)
			{			
				g-=2;	
				if(g<=0)
					g=0;
			}
			if(x>=120 && x<150)
			{			
				r+=2;
				if(r>=63)
					r=63;
			}
			if(x>=150 && x<160)
			{				
				b-=2;
				if(b<=0)
					b=0;
			}
		}
	}
}
/***********OLED Text Output Functions***************/

void OLED_Puts( char * pString )
{
    while (*pString != '\0')
        OLED_Putc( *pString++ );
}

void OLED_Putc( U8 ch )
{
	U8 	i,j;
	U16 temp;
	U16 char_start;
	U8 	char_width;
	U16 pack_char;
	U8  cursor_Y;

	cursor_Y = 	OLED_CursorY;

	U16 bit_count[] = {										//Mask Bits
						0x8000,0x4000,0x2000,0x1000,
						0x0800,0x0400,0x0200,0x0100,
						0x0080,0x0040,0x0020,0x0010,
						0x0008,0x0004,0x0002,0x0001
					  };

	char_start = (ch-32)*FONT16_SIZE;					//calculate character start position
	
	char_width = Font_Data[char_start];					//Get the Character Width size from the first byte of the data
		
	char_start++; 										

	for(i=0;i<(FONT16_SIZE-1);i+=2)
	{
		OLED_Set_Cursor(OLED_CursorX,cursor_Y++);
	
		pack_char = Font_Data[char_start+i] << 8;
		pack_char |= Font_Data[char_start+i+1];

		for(j=0;j<char_width;j++)
		{	
			Write_Register(rDDRAM_DATA_ACCESS_PORT);			
			temp = (pack_char & bit_count[j]);
			if(temp)
			{ 
				Write_6BitDDRAM(OLED_Red);
				Write_6BitDDRAM(OLED_Green);
				Write_6BitDDRAM(OLED_Blue);
			}
			else
			{
				Write_6BitDDRAM(0x00);
				Write_6BitDDRAM(0x00);
				Write_6BitDDRAM(0x00);
			}
		}	

	}

	OLED_CursorX += char_width;
}

/***********OLED Initialization code **********/
void  OLED_Init(void)						// OLED Initialization 
{

	/*********Ports I/O Set up, only work for PIC32**********/
	mPORTBSetBits( BIT_15 | BIT_14);
    mPORTBSetPinsDigitalOut( BIT_15 | BIT_14);

	mPORTDSetBits( BIT_11 | BIT_5 | BIT_4 );				
	mPORTDSetPinsDigitalOut( BIT_11 | BIT_5 | BIT_4 );

	mPORTEClearBits( BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0 );
	mPORTESetPinsDigitalOut(  BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0 );
	
	mPORTGClearBits( BIT_0 );
	mPORTGSetPinsDigitalOut(  BIT_0 );
	
	/************OLED Initialization Start******************/
	OLED_Reset();
	
	Write_Command(rREDUCE_CURRENT,0x03);
	OLED_Delay(0x10);
	//Reg:04h Action:Normal current and PS OFF
	Write_Command(rREDUCE_CURRENT,0x00);
	OLED_Delay(0x10);
	//Reg:3Bh Action:Screen Saver OFF
	Write_Command(rSCREEN_SAVER_CONTEROL,0x00);
	//Reg:02h Action:Export1 U16ernal clock/OSC with external resister/Internal OSC ON
	Write_Command(rOSC_CTL,0x01);
	//Reg:03h Action:FR=120Hz DIV=1
	Write_Command(rCLOCK_DIV,0x90);
	//Reg:80h Action:PDAC OFF,DDAC OFF/Reference Volt.control with external resister
	Write_Command(rIREF,0x00);
	//Reg:08h Action:set color R preU8ge time
	Write_Command(rPRECHARGE_TIME_R,0x03);
	//Reg:09h Action:set color G preU8ge time
	Write_Command(rPRECHARGE_TIME_G,0x05);
	//Reg:0Ah Action:set color B preU8ge tiem
	Write_Command(rPRECHARGE_TIME_B,0x05);
	//Reg:0Bh Action:set color R preU8ge current
	Write_Command(rPRECHARGE_Current_R,0x0a);
	//Reg:0Ch Action:set color G preU8ge current
	Write_Command(rPRECHARGE_Current_G,0x0a);
	//Reg:0Dh Action:set color B preU8ge current
	Write_Command(rPRECHARGE_Current_B,0x0a);
	//Reg:10h Action:set color R dot driving current
	Write_Command(rDRIVING_CURRENT_R,0x56);
	//Reg:11h Action:set color G dot driving current
	Write_Command(rDRIVING_CURRENT_G,0x4D);
	//Reg:12h Action:set color B dot driving current
	Write_Command(rDRIVING_CURRENT_B,0x46);
	//Reg:13h Action:Col D0 to D159/col normal display
	Write_Command(rDISPLAY_MODE_SET,0x00);
	//Reg:14h Action:MPU mode
	Write_Command(rRGB_IF,0x31);
	//Reg:16h Action: 6btis triple transfer,262K support
	Write_Command(rMEMORY_WRITE_MODE,0x76); // The data is continuously written horizontally
	//Write_Command(rMEMORY_WRITE_MODE,0x77); // The data is continuously written vertically
	//Reg:17h Action:Memory addr.X start
	Write_Command(rMX1_ADDR,0x00);
	//Reg:18h Action:Memory addr.X end
	Write_Command(rMX2_ADDR,0x9f);
	//Reg:18h Action:Memory addr.Y start
	Write_Command(rMY1_ADDR,0x00);
	//Reg:1Ah Action:Memory addr.Y end
	Write_Command(rMY2_ADDR,0x7f);
	//Reg:20h Action:Memory X start addr.
	Write_Command(rMEMORY_ACCESS_POINTER_X,0x00);
	//Reg:21h Action:Memory Y start addr.
	Write_Command(rMEMORY_ACCESS_POINTER_Y,0x00);
	//Reg:28h Action:Display duty ratio
	Write_Command(rDUTY,0x7f);
	//Reg:29h Action:Display start line
	Write_Command(rDSL,0x00);
	//Reg:2Eh Action:Display First screen X start poU16
	Write_Command(rD1_DDRAM_FAC,0x00);
	//Reg:2Fh Action:Display First screen Y start poU16
	Write_Command(rD1_DDRAM_FAR,0x00);
	//Reg:31h Action:Display Second screen X start poU16
	Write_Command(rD2_DDRAM_SAC,0x00);
	//Reg:32h Action:Display Second screen Y start poU16
	Write_Command(rD2_DDRAM_SAR,0x00);
	//Reg:33h Action:Display size X start
	Write_Command(rSCR1_FX1,0x00);
	//Reg:34h Action:Display size X end
	Write_Command(rSCR1_FX2,0x9f);
	//Reg:35h Action:Display size Y start
	Write_Command(rSCR1_FY1,0x00);
	//Reg:36h Action:Display size Y end
	Write_Command(rSCR1_FY2,0x7f);
	//Reg:06h Action:Scan signal is high level at preU8ge period/Dispaly ON
	Write_Command(rDISP_ON_OFF,0x01);
	//Clear DDRAM
	Clear_DDRAM( );
}

